﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.Office.Interop.Word;
using System.IO;
using IWord = Microsoft.Office.Interop.Word;
using System.Text;
using System.Collections;

public partial class Fckeditor_editor_plugins_ImportWord_ImportWord : System.Web.UI.Page
{
    //Html文件名
    private string _htmlFileName;
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    /// <summary>
    /// 上传Word文档
    /// </summary>
    /// <param name="inputFile"></param>
    /// <param name="filePath"></param>
    private string UpLoadFile(HtmlInputFile inputFile)
    {
        string fileName, fileExtension;

        //建立上传对象
        HttpPostedFile postedFile = inputFile.PostedFile;

        fileName = "(" + DateTime.Now.ToFileTime() + ")" + System.IO.Path.GetFileName(postedFile.FileName);

        fileExtension = System.IO.Path.GetExtension(fileName);



        //上传图片保存Base路径 如果修改此路径需要同时修改图片地址替换路径(在212行附件)

        string phyPath = Server.MapPath(System.Configuration.ConfigurationManager.AppSettings["FCKeditor:UserFilesPath"].ToString()) + "ImportWord\\";

        //判断路径是否存在,若不存在则创建路径
        DirectoryInfo upDir = new DirectoryInfo(phyPath);


        if (!upDir.Exists)
        {
            upDir.Create();
        }

        phyPath = phyPath + CreateDir(phyPath);

        //保存文件
        try
        {
            postedFile.SaveAs(phyPath + fileName);
        }
        catch
        {

        }
        return phyPath + fileName;
    }

    private string CreateDir(string path)
    {
        DateTime dt = DateTime.Now;
        string year = dt.Year.ToString();
        string month = dt.Month.ToString();
        string day = dt.Day.ToString();
        string Dir = "";
        if (!new DirectoryInfo(path + year).Exists)
        {
            Directory.CreateDirectory(path + year);
            Dir = year + @"\";
        }
        else
        {
            Dir = year + @"\";
        }
        if (!new DirectoryInfo(path + year + @"\" + month).Exists)
        {
            Directory.CreateDirectory(path + year + @"\" + month);
            Dir = year + @"\" + month + @"\";
        }
        else
        {
            Dir = year + @"\" + month + @"\";
        }
        if (!new DirectoryInfo(path + year + @"\" + month + @"\" + day).Exists)
        {
            Directory.CreateDirectory(path + year + @"\" + month + @"\" + day);
            Dir = year + @"\" + month + @"\" + day + @"\";
        }
        else
        {
            Dir = year + @"\" + month + @"\" + day + @"\";
        }
        return Dir;
        //string FilePath = path + year + @"\" + month + @"\" + DateTime.Now.ToFileTime() + @"." + FileType;
    }

    /// <summary>
    /// word转成html
    /// </summary>
    /// <param name="wordFileName"></param>
    private string WordToHtml(object wordFileName)
    {
        //在此处放置用户代码以初始化页面
        IWord.ApplicationClass word = new IWord.ApplicationClass();
        Type wordType = word.GetType();
        Documents docs = word.Documents;

        //打开文件
        Type docsType = docs.GetType();
        Document doc = (Document)docsType.InvokeMember("Open",
        System.Reflection.BindingFlags.InvokeMethod, null, docs, new Object[] { wordFileName, true, true });

        //转换格式，另存为
        Type docType = doc.GetType();

        string wordSaveFileName = wordFileName.ToString();
        string strSaveFileName = wordSaveFileName.Substring(0, wordSaveFileName.Length - 3) + "html";
        object saveFileName = (object)strSaveFileName;
        //下面是Microsoft Word 9 Object Library的写法，如果是10，可能写成如下，不明之处欢迎到Programbbs.com讨论
        /*
        docType.InvokeMember("SaveAs", System.Reflection.BindingFlags.InvokeMethod,
         null, doc, new object[]{saveFileName, Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatFilteredHTML});
        */
        ///其它格式：
        ///wdFormatHTML
        ///wdFormatDocument
        ///wdFormatDOSText
        ///wdFormatDOSTextLineBreaks
        ///wdFormatEncodedText
        ///wdFormatRTF
        ///wdFormatTemplate
        ///wdFormatText
        ///wdFormatTextLineBreaks
        ///wdFormatUnicodeText
        docType.InvokeMember("SaveAs", System.Reflection.BindingFlags.InvokeMethod,
         null, doc, new object[] { saveFileName, WdSaveFormat.wdFormatHTML });

        docType.InvokeMember("Close", System.Reflection.BindingFlags.InvokeMethod,
         null, doc, null);

        //退出 Word
        wordType.InvokeMember("Quit", System.Reflection.BindingFlags.InvokeMethod,
         null, word, null);

        return saveFileName.ToString();
    }

    /// <summary>
    /// 上传并处理word文档
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnUpload_Click(object sender, EventArgs e)
    {
        try
        {
            string strFilename = UpLoadFile(this.fileWord);

            _htmlFileName = WordToHtml((object)strFilename);

            findUsedFromHtml(getHtml(_htmlFileName), strFilename);

            //删除文件
            System.IO.File.Delete(_htmlFileName);
            System.IO.File.Delete(strFilename);
        }
        catch(Exception ex)
        {
            Response.Write(ex.ToString());
        }
    }

    /// <summary>
    /// 读取html文件，返回字符串
    /// </summary>
    /// <param name="strHtmlFileName"></param>
    /// <returns></returns>
    private string getHtml(string strHtmlFileName)
    {
        System.Text.Encoding encoding = System.Text.Encoding.GetEncoding("gb2312");

        StreamReader sr = new StreamReader(strHtmlFileName, encoding);

        string str = sr.ReadToEnd();

        sr.Close();

        return str;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="strHtml"></param>
    /// <returns></returns>
    private void findUsedFromHtml(string strHtml, string strFileName)
    {
        string strStyle;
        string strBody;

        // stytle 部分
        int index = 0;
        int intStyleStart = 0;
        int intStyleEnd = 0;

        while (index < strHtml.Length)
        {
            int intStyleStartTmp = strHtml.IndexOf("<style>", index);
            if (intStyleStartTmp == -1)
            {
                break;
            }
            int intContentStart = strHtml.IndexOf("<!--", intStyleStartTmp);
            if (intContentStart - intStyleStartTmp == 9)
            {
                intStyleStart = intStyleStartTmp;
                break;
            }
            else
            {
                index = intStyleStartTmp + 7;
            }
        }

        index = 0;
        while (index < strHtml.Length)
        {
            int intContentEndTmp = strHtml.IndexOf("-->", index);
            if (intContentEndTmp == -1)
            {
                break;
            }
            int intStyleEndTmp = strHtml.IndexOf("</style>", intContentEndTmp);
            if (intStyleEndTmp - intContentEndTmp == 5)
            {
                intStyleEnd = intStyleEndTmp;
                break;
            }
            else
            {
                index = intContentEndTmp + 4;
            }
        }

        strStyle = strHtml.Substring(intStyleStart, intStyleEnd - intStyleStart + 8);

        // Body部分
        int bodyStart = strHtml.IndexOf("<body");
        for (int i = bodyStart; i < strHtml.Length; i++)
        {
            if (strHtml[i].ToString() == ">")
            {
                bodyStart = i + 1;
                break;
            }
        }
        int bodyEnd = strHtml.IndexOf("</body>");

      
        strBody = strHtml.Substring(bodyStart, bodyEnd - bodyStart);

        /*
        bool ischeck = TagsChecker.check(strBody);
        if (!ischeck)
        {
            strBody = TagsChecker.fix(strBody);
        }
        */
         
        //替换图片地址
        string fullName = strFileName.Substring(strFileName.LastIndexOf("\\") + 1);
        string strOld = fullName.Replace("doc", "files").Replace(" ", "%20");

        string strNew = Request.Url.Scheme + ":"  + "//" + Request.Url.Authority + "/EEPwebClient/UploadFile/CMSUpLoadFiles/FckUpload/ImportWord/" +
            CreateDir(Server.MapPath(System.Configuration.ConfigurationManager.AppSettings["FCKeditor:UserFilesPath"].ToString()).Replace(@"\","/") + "ImportWord\\") + strOld;


        strBody = strBody.Replace(strOld, strNew);
        strBody = strBody.Replace("v:imagedata", "img");
        strBody = strBody.Replace("</v:imagedata>", "");

        //Sgxcn临时调试用-但不可去掉
        this.TextArea1.InnerText = strStyle;
        this.Textarea2.InnerText = strBody;

        //更改信息
        pnlOk.Visible = true;
        pnlUpload.Visible = false;


        GC.Collect();
    }

    #region HTML是否闭合
    class TagsList
    {
        private ArrayList data;

        public int Size
        {
            get
            {
                return data.Count;
            }
        }

        public TagsList()
        {
            data = new ArrayList();
        }

        public void add(String str)
        {
            data.Add(str);
        }

        public string get(int index)
        {
            if (index < data.Count)
                return (string)data[index];
            else
                return null;
        }

        public bool remove(string str)
        {
            if (data.IndexOf(str) == -1) return false;
            data.Remove(str);
            return true;
        }

        public void remove(int index)
        {
            data.RemoveAt(index);
        }
    }

    public class TagsChecker
    {
        public static bool check(string str)
        {
            TagsList[] unclosedTags = getUnclosedTags(str);

            if (unclosedTags[0].Size != 0)
            {
                return false;
            }
            for (int i = 0; i < unclosedTags[1].Size; i++)
            {
                if (unclosedTags[1].get(i) != null)
                    return false;
            }

            return true;
        }

        public static string fix(String str)
        {
            StringBuilder fixeds = new StringBuilder(); // 存放修复后的字符串
            TagsList[] unclosedTags = getUnclosedTags(str);

            // 生成新字符串
            for (int i = unclosedTags[0].Size - 1; i > -1; i--)
            {
                fixeds.Append("<" + unclosedTags[0].get(i) + ">");
            }

            fixeds.Append(str);

            for (int i = unclosedTags[1].Size - 1; i > -1; i--)
            {
                String s = null;
                if ((s = unclosedTags[1].get(i)) != null)
                {
                    fixeds.Append("</" + s + ">");
                }
            }

            return fixeds.ToString();
        }
    }

    private static TagsList[] getUnclosedTags(String str)
        {
            StringBuilder temp = new StringBuilder(); // 存放标签
            TagsList[] unclosedTags = new TagsList[2];
            unclosedTags[0] = new TagsList(); // 前不闭合，如有</div>而前面没有<div>
            unclosedTags[1] = new TagsList(); // 后不闭合，如有<div>而后面没有</div>
            bool flag = false; // 记录双引号"或单引号'
            char currentJump = ' '; // 记录需要跳过''还是""

            char current = ' ', last = ' '; // 当前 & 上一个

            // 开始判断
            for (int i = 0; i < str.Length; )
            {
                current = str[i++]; // 读取一个字符
                if (current == '"' || current == '\'')
                {
                    flag = flag ? false : true; // 若为引号，flag翻转
                    currentJump = current;
                    if (flag)
                    {
                        while (i < str.Length && str[i++] != currentJump)
                            ; // 跳过引号之间的部分
                        flag = false;
                    }
                }
                else if (current == '<')
                { // 开始提取标签
                    current = str[i++];
                    if (current == '/')
                    { // 标签的闭合部分，如</div>
                        current = str[i++];

                        // 读取标签
                        while (i < str.Length && current != '>')
                        {
                            temp.Append(current);
                            current = str[i++];
                        }

                        // 从tags_bottom移除一个闭合的标签
                        if (!unclosedTags[1].remove(temp.ToString()))
                        { // 若移除失败，说明前面没有需要闭合的标签
                            unclosedTags[0].add(temp.ToString()); // 此标签需要前闭合
                        }
                        temp.Remove(0, temp.Length); // 清空temp
                    }
                    else
                    { // 标签的前部分，如<div>
                        last = current;
                        while (i < str.Length && current != ' '
                                && current != ' ' && current != '>')
                        {
                            temp.Append(current);
                            last = current;
                            current = str[i++];
                        }

                        // 已经读取到标签，跳过其他内容，如<div id=test>跳过id=test
                        while (i < str.Length && current != '>')
                        {
                            last = current;
                            current = str[i++];
                            if (current == '"' || current == '\'')
                            { // 判断双引号
                                flag = flag ? false : true;
                                currentJump = current;
                                if (flag)
                                { // 若引号不闭合，跳过到下一个引号之间的内容
                                    while (i < str.Length && str[i++] != currentJump)
                                        ;
                                    current = str[i++];
                                    flag = false;
                                }
                            }
                        }
                        if (last != '/' && current == '>') // 判断这种类型：<TagName />
                            unclosedTags[1].add(temp.ToString());
                        temp.Remove(0, temp.Length);
                    }
                }
            }
            return unclosedTags;
        }

    #endregion
}

